from fastapi import Depends
from sqlalchemy import select, desc, update, delete
import uuid
import typing as T
from datetime import datetime
import json
from ...common.chat import RoleType
from ...pojo.dto.UserSessionDTO import UserSessionDTO
from ...pojo.entity import User2Session, UserChatHistory
from ...pojo.vo import User2SessionVO, UserChatHistoryVO
from ..mapper.UserSessionMapper import UserSessionMapper, _UserSessionMapper
from ..mapper._ChatHistoryCacheMapper import _chatHistoryCacheMapper


class UserSessionServiceImpl:
    mapper: _UserSessionMapper = None

    def __call__(self, mapper: UserSessionMapper):
        self.mapper = mapper
        return self

    async def create_session(self, userSessionDTO: UserSessionDTO):
        createTime = datetime.now()
        alias = userSessionDTO.alias or f"{uuid.uuid4()}"
        entity = User2Session(
            userId=userSessionDTO.userId,
            alias=alias,
            createTime=createTime,
        )
        await self.mapper.insert_by_entity(entity)

    async def get_session_by_user_id(self, userId: int):
        sql = (
            select(User2Session)
            .where(User2Session.userId == userId)
            .order_by(desc(User2Session.createTime))
        )
        result = await self.mapper.select(sql)
        result = [User2SessionVO(**item.model_dump()) for item in result]
        return result

    async def _sync_cache_to_db(self, sessionId: int):
        # 检查是否需要同步缓存到数据库
        persisted = await _chatHistoryCacheMapper.get_persisted(sessionId)
        if persisted is not None:
            length = await _chatHistoryCacheMapper.get_cache_length_by_session_id(sessionId)
            number = length - persisted
            if number > 0:
                history = await _chatHistoryCacheMapper.get_cache_by_session_id(
                    sessionId, number
                )
                messages = [
                    UserChatHistory(
                        sessionId=sessionId,
                        content=json.dumps(msg[1], ensure_ascii=False),
                        isAi=msg[0] == RoleType.AI,
                    )
                    for msg in history
                ]
                await _chatHistoryCacheMapper.set_persisted(sessionId, length)
                await self.mapper.insert_batch_by_entity(messages)

    async def get_chat_history(self, sessionId: int, count: int):
        await self._sync_cache_to_db(sessionId)
        sql = (
            select(UserChatHistory)
            .where(UserChatHistory.sessionId == sessionId)
            .order_by(desc(UserChatHistory.id))
        )
        if count != -1:
            sql = sql.limit(count)
        result: T.List[UserChatHistory] = await self.mapper.select(sql)
        result = [
            UserChatHistoryVO(
                id=item.id,
                isAi=item.isAi,
                sessionId=item.sessionId,
                content=json.loads(item.content),
            )
            for item in result
        ]
        return result

    async def update_session_name_by_session_id(self, sessionId: int, name: str):
        sql = (
            update(User2Session).where(User2Session.id == sessionId).values(alias=name)
        )
        await self.mapper.update(sql)

    async def delete_session_by_session_id(self, sessionId: int):
        sql = delete(User2Session).where(User2Session.id == sessionId)
        await self.mapper.delete(sql)


UserSessionService = T.Annotated[
    UserSessionServiceImpl, Depends(UserSessionServiceImpl())
]
